/**
 * ============万年历控制器模块开始===========
 * 万年历控制器 - Calendar Controller
 * 
 * 功能说明：
 * - 处理万年历相关的API请求，提供农历、节气、宜忌等信息
 * - 支持单日查询、月度查询、黄道吉日查询等功能
 * - 集成lunar_service服务，提供准确的万年历计算
 * - 提供RESTful API接口，返回标准JSON格式数据
 * 
 * 依赖模块：
 * - lunar_service: 农历计算服务，提供万年历核心算法
 * 
 * API端点：
 * - GET /calendar/info: 获取指定日期的万年历信息
 * - GET /calendar/month: 获取指定月份的万年历信息
 * - GET /calendar/auspicious: 获取黄道吉日信息
 * 
 * Handle calendar-related API requests
 */

const lunarService = require('../services/lunar_service');

/**
 * 万年历控制器类 - Calendar Controller Class
 * 
 * 该类封装了所有万年历相关的业务逻辑处理方法
 * 每个方法对应一个API端点，负责参数验证、业务处理和响应返回
 * 
 * 设计原则：
 * - 单一职责：每个方法只处理一种类型的万年历查询
 * - 参数验证：严格验证输入参数的格式和范围
 * - 错误处理：统一的错误处理和响应格式
 * - 日志记录：记录关键操作和异常信息
 */
class CalendarController {
  /**
   * ============获取单日万年历信息功能开始===========
   * 获取指定日期的万年历信息
   * Get calendar information for specified date
   * 
   * @param {Object} req - Express请求对象
   * @param {Object} res - Express响应对象
   * @returns {Promise<void>} 无返回值，通过res对象返回JSON响应
   * @throws {Error} 当参数验证失败或服务调用失败时抛出异常
   * 
   * 功能说明：
   * - 根据公历日期查询对应的农历信息
   * - 包含农历日期、节气、宜忌、星宿、生肖等详细信息
   * - 支持1900-2100年范围内的日期查询
   * - 返回完整的万年历数据结构
   * 
   * 请求参数（Query Parameters）：
   * - year: 年份，整数，范围1900-2100
   * - month: 月份，整数，范围1-12
   * - day: 日期，整数，范围1-31（根据月份调整）
   * 
   * 响应格式：
   * {
   *   success: boolean,
   *   message: string,
   *   data: {
   *     solar: { year, month, day },
   *     lunar: { year, month, day, isLeap },
   *     ganzhi: { year, month, day },
   *     zodiac: string,
   *     constellation: string,
   *     solarTerm: string,
   *     festivals: string[],
   *     suitable: string[],
   *     avoid: string[]
   *   }
   * }
   * 
   * 使用示例：
   * GET /api/calendar/info?year=2024&month=1&day=15
   * 
   * 异常处理：
   * - 400: 参数缺失或格式错误
   * - 400: 日期范围超出支持范围
   * - 500: 服务器内部错误
   */
  async getCalendarInfo(req, res) {
    try {
      // 第一步：获取请求参数 - Step 1: Get request parameters
      const { year, month, day } = req.query;
      
      // 第二步：参数存在性验证 - Step 2: Parameter existence validation
      if (!year || !month || !day) {
        return res.status(400).json({
          success: false,
          message: '缺少必要参数：年、月、日',
          data: null
        });
      }
      
      // 第三步：参数类型转换和格式验证 - Step 3: Parameter type conversion and format validation
      const yearNum = parseInt(year);
      const monthNum = parseInt(month);
      const dayNum = parseInt(day);
      
      // 检查转换后的数值是否有效 - Check if converted numbers are valid
      if (isNaN(yearNum) || isNaN(monthNum) || isNaN(dayNum)) {
        return res.status(400).json({
          success: false,
          message: '日期参数格式错误，请提供有效的数字',
          data: null
        });
      }
      
      // 第四步：年份范围验证 - Step 4: Year range validation
      if (yearNum < 1900 || yearNum > 2100) {
        return res.status(400).json({
          success: false,
          message: '年份范围应在1900-2100之间',
          data: null
        });
      }
      
      // 第五步：月份范围验证 - Step 5: Month range validation
      if (monthNum < 1 || monthNum > 12) {
        return res.status(400).json({
          success: false,
          message: '月份范围应在1-12之间',
          data: null
        });
      }

      // 第六步：日期范围验证 - Step 6: Day range validation
      if (dayNum < 1 || dayNum > 31) {
        return res.status(400).json({
          success: false,
          message: '日期范围应在1-31之间',
          data: null
        });
      }

      // 第七步：调用农历服务获取万年历信息 - Step 7: Call lunar service to get calendar info
      // lunarService.getCalendarInfo() 方法根据公历日期计算对应的农历信息
      const calendarInfo = await lunarService.getCalendarInfo(yearNum, monthNum, dayNum);
      
      // 第八步：返回成功响应 - Step 8: Return success response
      res.json({
        success: true,
        message: '获取万年历信息成功',
        data: calendarInfo
      });
      
    } catch (error) {
      // 第九步：错误处理 - Step 9: Error handling
      console.error('获取万年历信息失败:', error);
      res.status(500).json({
        success: false,
        message: '获取万年历信息失败，请稍后重试',
        data: null
      });
    }
  }

  /**
   * ============获取月度万年历信息功能开始===========
   * 获取指定月份的万年历信息
   * Get calendar information for specified month
   * 
   * @param {Object} req - Express请求对象
   * @param {Object} res - Express响应对象
   * @returns {Promise<void>} 无返回值，通过res对象返回JSON响应
   * @throws {Error} 当参数验证失败或服务调用失败时抛出异常
   * 
   * 功能说明：
   * - 获取指定月份所有日期的万年历信息
   * - 返回该月每一天的农历、节气、宜忌等信息
   * - 适用于日历组件的月视图显示
   * - 批量处理提高查询效率
   * 
   * 请求参数（Query Parameters）：
   * - year: 年份，整数，范围1900-2100
   * - month: 月份，整数，范围1-12
   * 
   * 响应格式：
   * {
   *   success: boolean,
   *   message: string,
   *   data: {
   *     year: number,
   *     month: number,
   *     days: [
   *       {
   *         day: number,
   *         solar: { year, month, day },
   *         lunar: { year, month, day, isLeap },
   *         ganzhi: { year, month, day },
   *         zodiac: string,
   *         solarTerm: string,
   *         festivals: string[],
   *         suitable: string[],
   *         avoid: string[]
   *       }
   *     ]
   *   }
   * }
   * 
   * 使用示例：
   * GET /api/calendar/month?year=2024&month=1
   * 
   * 异常处理：
   * - 400: 参数缺失或格式错误
   * - 400: 日期范围超出支持范围
   * - 500: 服务器内部错误
   */
  async getMonthCalendar(req, res) {
    try {
      // 第一步：获取请求参数 - Step 1: Get request parameters
      const { year, month } = req.query;
      
      // 第二步：参数存在性验证 - Step 2: Parameter existence validation
      if (!year || !month) {
        return res.status(400).json({
          success: false,
          message: '缺少必要参数：年、月',
          data: null
        });
      }
      
      // 第三步：参数类型转换和格式验证 - Step 3: Parameter type conversion and format validation
      const yearNum = parseInt(year);
      const monthNum = parseInt(month);
      
      if (isNaN(yearNum) || isNaN(monthNum)) {
        return res.status(400).json({
          success: false,
          message: '日期参数格式错误，请提供有效的数字',
          data: null
        });
      }
      
      // 第四步：年份和月份范围验证 - Step 4: Year and month range validation
      if (yearNum < 1900 || yearNum > 2100) {
        return res.status(400).json({
          success: false,
          message: '年份范围应在1900-2100之间',
          data: null
        });
      }
      
      if (monthNum < 1 || monthNum > 12) {
        return res.status(400).json({
          success: false,
          message: '月份范围应在1-12之间',
          data: null
        });
      }

      // 第五步：计算该月的天数 - Step 5: Calculate days in the month
      // 使用Date对象的特性：设置日期为0会得到上个月的最后一天
      const daysInMonth = new Date(yearNum, monthNum, 0).getDate();
      
      // 第六步：循环获取该月每一天的万年历信息 - Step 6: Loop to get calendar info for each day
      const monthData = [];
      for (let day = 1; day <= daysInMonth; day++) {
        try {
          // 调用农历服务获取每一天的信息 - Call lunar service for each day
          const dayInfo = await lunarService.getCalendarInfo(yearNum, monthNum, day);
          monthData.push({
            day: day,
            ...dayInfo
          });
        } catch (dayError) {
          // 单日错误不影响整个月的查询 - Single day error doesn't affect the whole month query
          console.error(`获取${yearNum}-${monthNum}-${day}信息失败:`, dayError);
          monthData.push({
            day: day,
            error: '该日期信息获取失败'
          });
        }
      }
      
      // 第七步：返回成功响应 - Step 7: Return success response
      res.json({
        success: true,
        message: '获取月度万年历信息成功',
        data: {
          year: yearNum,
          month: monthNum,
          daysInMonth: daysInMonth,
          days: monthData
        }
      });
      
    } catch (error) {
      // 第八步：错误处理 - Step 8: Error handling
      console.error('获取月度万年历信息失败:', error);
      res.status(500).json({
        success: false,
        message: '获取月度万年历信息失败，请稍后重试',
        data: null
      });
    }
  }

  /**
   * ============获取黄道吉日功能开始===========
   * 获取指定月份的黄道吉日
   * Get auspicious days for specified month
   * 
   * @param {Object} req - Express请求对象
   * @param {Object} res - Express响应对象
   * @returns {Promise<void>} 无返回值，通过res对象返回JSON响应
   * @throws {Error} 当参数验证失败或服务调用失败时抛出异常
   * 
   * 功能说明：
   * - 根据传统农历算法筛选出黄道吉日
   * - 提供适宜进行重要活动的日期建议
   * - 包含每个吉日的具体宜忌事项
   * - 支持不同类型活动的吉日查询
   * 
   * 请求参数（Query Parameters）：
   * - year: 年份，整数，范围1900-2100
   * - month: 月份，整数，范围1-12
   * - type?: 活动类型，可选，如"wedding"、"moving"、"business"等
   * 
   * 响应格式：
   * {
   *   success: boolean,
   *   message: string,
   *   data: {
   *     year: number,
   *     month: number,
   *     auspiciousDays: [
   *       {
   *         day: number,
   *         lunar: { year, month, day },
   *         ganzhi: { year, month, day },
   *         suitable: string[],
   *         avoid: string[],
   *         rating: number,
   *         description: string
   *       }
   *     ]
   *   }
   * }
   * 
   * 使用示例：
   * GET /api/calendar/auspicious?year=2024&month=1&type=wedding
   * 
   * 异常处理：
   * - 400: 参数缺失或格式错误
   * - 400: 日期范围超出支持范围
   * - 500: 服务器内部错误
   */
  async getAuspiciousDays(req, res) {
    try {
      // 第一步：获取请求参数 - Step 1: Get request parameters
      const { year, month, type } = req.query;
      
      // 第二步：参数存在性验证 - Step 2: Parameter existence validation
      if (!year || !month) {
        return res.status(400).json({
          success: false,
          message: '缺少必要参数：年、月',
          data: null
        });
      }
      
      // 第三步：参数类型转换和格式验证 - Step 3: Parameter type conversion and format validation
      const yearNum = parseInt(year);
      const monthNum = parseInt(month);
      
      if (isNaN(yearNum) || isNaN(monthNum)) {
        return res.status(400).json({
          success: false,
          message: '日期参数格式错误，请提供有效的数字',
          data: null
        });
      }
      
      // 第四步：年份和月份范围验证 - Step 4: Year and month range validation
      if (yearNum < 1900 || yearNum > 2100) {
        return res.status(400).json({
          success: false,
          message: '年份范围应在1900-2100之间',
          data: null
        });
      }
      
      if (monthNum < 1 || monthNum > 12) {
        return res.status(400).json({
          success: false,
          message: '月份范围应在1-12之间',
          data: null
        });
      }

      // 第五步：调用农历服务获取黄道吉日 - Step 5: Call lunar service to get auspicious days
      // lunarService.getAuspiciousDays() 方法根据农历算法筛选吉日
      const auspiciousDays = await lunarService.getAuspiciousDays(yearNum, monthNum, type);
      
      // 第六步：返回成功响应 - Step 6: Return success response
      res.json({
        success: true,
        message: '获取黄道吉日信息成功',
        data: {
          year: yearNum,
          month: monthNum,
          type: type || 'general',
          auspiciousDays: auspiciousDays
        }
      });
      
    } catch (error) {
      // 第七步：错误处理 - Step 7: Error handling
      console.error('获取黄道吉日信息失败:', error);
      res.status(500).json({
        success: false,
        message: '获取黄道吉日信息失败，请稍后重试',
        data: null
      });
    }
  }
}

// 导出控制器实例 - Export controller instance
// 使用单例模式，确保整个应用中只有一个控制器实例
module.exports = new CalendarController();